/**
 * 
 */
package com.gragra.sampling.binary;
import com.gragra.sampling.PopulationProbabilityAssigner;
import com.gragra.sampling.sequentialStructure.WordAndTagHolder;
/**
 * @author Christoph Teichmann
 * 17.09.2013
 */
public class BinaryInside extends BinaryChart
{
	/**
	 * 
	 */
	private AVLTripleCounter ruleProbs = new AVLTripleCounter();
	/**
	 * 
	 */
	private PairCounter norms = new PairCounter();
	/**
	 * @param wth
	 * @param threads
	 * @param cs
	 */
	public BinaryInside(WordAndTagHolder wth, int threads, ConvertSample cs, boolean sampleHead)
	{super(wth, threads, cs,sampleHead);}
	@Override
	protected double getLogChoiceProb(int from, int to, int middle, int thread)
	{
		double ret = this.ruleProbs.getAmount((short) from,(short) to,(short) middle);
		return ret;
	}
	@Override
	protected double getLogNormalizer(int from, int to, int thread)
	{
		double ret = this.norms.get(from, to);
		return ret;
	}
	@Override
	protected void createChart(double annealing, int thread, PopulationProbabilityAssigner ba)
	{
		this.norms.clear();
		this.ruleProbs.clear();
		ChartAbleAssigner cas = (ChartAbleAssigner) ba;
		for(int dist=2;dist<=this.getLength();++dist)
		{
			for(int start=0;start+dist<=this.getLength();++start)
			{
				int end = start+dist;
				double sum = Double.NEGATIVE_INFINITY;
				for(int middle=start+1;middle<end;++middle)
				{
					double here = cas.getTransitionLogLike(this, thread, start, middle, end)
													+this.norms.get(start, middle)+this.norms.get(middle, end);
					double max = Math.max(sum, here);
					sum = Math.log(Math.exp(sum-max)+Math.exp(here-max))+max;
					this.ruleProbs.setVal((short) start,(short) end,(short) middle, here);
				}
				this.norms.set(start, end, sum);
			}
		}
	}
	@Override
	protected void clearChart()
	{
		this.norms.clear();
		this.ruleProbs.clear();
	}
	/**
	 * 
	 */
	private final static double HALF = Math.log(0.5);
	@Override
	protected double getLogNormLeftProb(int left, int right, int middle,
			int thread)
	{return 0.0;}
	@Override
	protected double getLogLeftProb(int left, int right, int middle, int thread)
	{return HALF;}
}